import java.util.*;

/**
 * @author LKQ
 * @date 2022/5/2 14:46
 * @description 并查集
 */
public class Solution {
    public static void main(String[] args) {

    }
    public List<List<String>> accountsMerge(List<List<String>> accounts) {
        Map<String, Integer> emailToIndex = new HashMap<>();
        Map<String, String> emailToName = new HashMap<>();
        int emailCount = 0;
        // 给每个邮箱编号
        for (List<String> ac: accounts) {
            String name = ac.get(0);
            int size = ac.size();
            for (int i = 1; i < size; i++) {
                String email = ac.get(i);
                if (!emailToIndex.containsKey(email)) {
                    emailToIndex.put(email, emailCount++);
                    emailToName.put(email, name);
                }
            }
        }
        UnionFind uf = new UnionFind(emailCount);
        for (List<String> ac : accounts) {
            String firstEmail = ac.get(1);
            int firstIndex = emailToIndex.get(firstEmail);
            int size = ac.size();
            for (int i = 2; i < size; i++) {
                String nextEmail = ac.get(i);
                int nextIndex = emailToIndex.get(nextEmail);
                // 合并不同邮箱编号
                uf.union(firstIndex, nextIndex);
            }
        }
        Map<Integer, List<String>> indexToEmails = new HashMap<>();
        for (String email : emailToIndex.keySet()) {
            int index = uf.find(emailToIndex.get(email));
            List<String> account = indexToEmails.getOrDefault(index, new ArrayList<String>());
            account.add(email);
            indexToEmails.put(index, account);
        }
        List<List<String>> merged = new ArrayList<List<String>>();
        for (List<String> emails : indexToEmails.values()) {
            Collections.sort(emails);
            String name = emailToName.get(emails.get(0));
            List<String> account = new ArrayList<String>();
            account.add(name);
            account.addAll(emails);
            merged.add(account);
        }
        return merged;

    }
}
class UnionFind{
    int[] parent;

    public UnionFind(int n) {
        parent = new int[n];
        for (int i = 0; i < n; i++) {
            parent[i] = i;
        }
    }
    public void union(int x, int y) {
        parent[find(x)] = find(y);
    }

    public int find(int x) {
        if (parent[x] != x) {
            parent[x] = find(parent[x]);
        }
        return parent[x];
    }
}
